--[[
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
    You should have received a copy of the GNU General Public License along
    with this program; if not, write to the Free Software Foundation, Inc.,
    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Detection for CVE-2015-2375 expects Compressed Office Doc (e.g., docx)
This lua script can be run standalone and verbosely on a Flash file with
echo "run()" | luajit -i <script name> <office file>
Darien Huss
--]]

require("zip")

function init (args)
    local needs = {}
    needs["http.response_body"] = tostring(true)
    return needs
end

--http://snippets.luacode.org/?p=snippets/String_to_Hex_String_68
function HexDumpString(str,spacer)
    return (
    string.gsub(str,"(.)",
    function (c)
        return string.format("%02X%s",string.byte(c), spacer or "\\")
    end)
    )
end

function doc_handler(t,verbose)
    rtn = 0
    tmpname = os.tmpname()
    
    tmp = io.open(tmpname,'w')
    tmp:write(t)
    tmp:close()

    z,err = zip.open(tmpname)
    local buffers = {}
    if z then
        for w in z:files() do
            if string.find(w.filename,"xl/tables/table%d+\.xml") then
                f = z:open(w.filename);
                u = f:read("*all")
                --convert to lowercase
                u = u:lower()
                f:close()
                if (verbose==1) then print("Checking " .. w.filename) end
                if string.find(u,"<x14:table",0,true) and string.find(u,"</x14:table>",0,true) then
                    for table in string.gmatch(u,"<x14:table[^>]*>(.-)</x14:table>") do
                        if string.len(table) >= 1976713 then
                            rtn2 = 1
                        end
                    end
                end
                if (verbose == 0) then
                    if rtn2 == 1 then return 1 end
                end
                if rtn2 == 1 then rtn = rtn2 end
            end
        end
    end
    if err then print(err) end
    if z then z:close() end
    os.remove(tmpname)
    return rtn
end

function common(t,o,verbose)
    rtn = 0
    if string.sub(t,1,4) == "PK\003\004" then
        rtn = doc_handler(t,verbose)
    end
    return rtn 
end

function match(args)
    local t = tostring(args["http.response_body"])
    local o = args["offset"]
    return common(t,o,0)
end

function run()
  local f = io.open(arg[1])
  local t = f:read("*all")
  f:close()
  common(t,4,1)
end